API do Spectrum Virtualize RESTful
A Interface de Programação de Aplicativos (API) do modelo Representational State Transfer (REST) Spectrum Virtualize consiste em destinos de comando que são usados para recuperar informações do sistema e para criar, modificar e excluir recursos do sistema. Esses destinos de comando permitem que parâmetros de comando sejam transmitidos sem revisão para a interface da linha de comandos do Spectrum Virtualize, que manipula especificações de parâmetros de análise quanto à validade e a relatórios de erro. Use o Protocolo de Transporte de Hipertexto Seguro (HTTPS) para se comunicar com êxito com o servidor da API RESTful.
O servidor da API RESTful não considera a segurança de transporte (como SSL), mas, em vez disso, assume que as solicitações são iniciadas a partir de um servidor local, seguro. O protocolo HTTPS fornece privacidade por meio da criptografia de dados. A API RESTful fornece mais segurança, requerendo autenticação de comando, que persiste por duas horas de atividade, ou 30 minutos de inatividade, o que ocorrer primeiro.
Os Localizadores Uniformes de Recursos (URLs) direcionam objetos de nó diferentes no sistema. O método HTTPS POST age em destinos de comandos que são especificados na URL. Para obter mais informações, consulte Destinos e Características do Comando da API RESTful. Para fazer mudanças ou visualizar informações sobre objetos diferentes no sistema, você deve criar e enviar uma solicitação ao sistema. É necessário que você forneça determinados elementos para o servidor da API RESTful para receber e converter a solicitação em um comando, conforme descrito na próxima seção.
Fazendo uma solicitação de HTTPS
https://system_node_ip: 7443/rest/command
Em
que:Todos os comandos, incluindo comandos LS, aceitam pelo menos um parâmetro nomeado. Como a API RESTful do Spectrum Virtualize é apenas um método POST, ela implementa uma convenção de anexar parâmetros posicionais ao URI e empacotar parâmetros nomeados no corpo da solicitação como sequências JavaScript Object Notation (JSON).
O método mais elegante para os destinos de comandos era adotar o POST exclusivamente.
Conforme mencionado, além da URL e do nome do destino do comando, outras informações são necessárias na linha de solicitação e no corpo da solicitação de HTTP que consideram a ação a ser tomada no objeto especificado. Na linha de solicitação, inclua o método HTTP POST. Inclua quaisquer parâmetros necessários (como nível do RAID ou endereço IP) no corpo da solicitação.
{'X-Auth-Username': 'superuser'}HTTP/1.1 200 OK
Servidor: lighttpd / 1.4.31
Data: data
Content-type: application/json; charset = UTF-8
Content-length: content_length
Conexão: fechada
{"attribute": "value"}
Para visualizar os destinos de comando da API e suas características, consulte Destinos e Características do Comando da API RESTful. Para ver um exemplo de como iniciar, consulte Introdução. Consulte Mensagens de Erro HTTP da API RESTful para obter uma lista completa de códigos de erro HTTP que você pode encontrar.
Destinos e Características do Comando da API RESTful
O Tabela 1 enfatiza o método POST para todos os comandos, incluindo /auth. Também mostra que você deve usar o token de autenticação que é retornado pelo destino de comando /auth para autenticar todos os outros comandos executados. Exceto para o destino de comando /auth, você executa comandos no endereço IP do sistema para que eles sejam executados pelo nó de configuração.
| Destinos de Comando | Método | Autenticação necessária | Executar no Nó de Configuração / Cluster |
|---|---|---|---|
| /auth | POST | Não | Não |
| Todos os outros destinos de comando | POST | sim | Sim |
As descrições dos destinos de comandos e seus parâmetros, e as descrições de outros comandos usados com menos frequência estão disponíveis na seção de comandos da CLI da documentação do produto.
| Destinos de Comando | ||
|---|---|---|
| /addhostclustermember | /addhostiogrp | /addhostport |
| /addvdiskaccess | /addvdiskcopy | /addvolumecopy |
| /auth | /chhost | /chnode |
| /chnodecanister | /chrcconsistgrp | /chrcrelationship |
| /chvdisk | /expandvdisksize | /lscurrentuser |
| /lseventlog | /lsfcconsistgrp | /lsfcmap |
| /lsfcmapcandidate | /lsfcmapdependentmaps | /lsfcmapprogress |
| /lshost | /lshostcluster | /lshostclustermember |
| /lshostclustervolumemap | /lshostiogrp | /lshostvdiskmap |
| /lsiogrp | /lsiogrphost | /lsmdiskgrp |
| /lsnode | /lsnodecanister | /lsnodehw |
| /lsnodecanisterhw | /lsnodecanisterstats | /lsnodecanistervpd |
| /lsnodehw | /lsnodestats | /lsnodevpd |
| /lspartnership | /lsrcrelationshipprogress | /lssystem |
| /lssystemip | /lssystemstats | /lsvdisk |
| /lsvdiskaccess | /lsvdiskcopy | /lsvdiskfcmapcopies |
| /lsvdiskfcmappings | /lsvdiskhostmap | /lsvdisksyncprogress |
| /mkfcconsistgrp | /mkfcmap | /mkfcpartnership |
| /mkhost | /mkhostcluster | /mkrcconsistgrp |
| /mkrcrelationship | /mkvdisk | /mkvdiskhostmap |
| /mkvolume | /mkvolumehostclustermap | /movevdisk |
| /prestartfcconsistgrp | /prestartfcmap | /rmfcmap |
| /rmhost | /rmhostcluster | /rmhostclustermember |
| /rmhostiogrp | /rmhostport | /rmvdisk |
| /rmvdiskaccess | /rmvdiskcopy | /rmvdiskhostmap |
| /rmvolume | /rmvolumecopy | /rmvolumehostclustermap |
| /startfcmap | /startrcconsistgrp | /startrcrelationship |
| /stopfcconsistgrp | /stopfcmap | /stoprcconsistgrp |
| /stoprcrelationship | ||
Visão geral de autenticação
Além da criptografia de dados, o servidor HTTPS requer autenticação de um nome de usuário e senha válidos para cada sessão da API. Use dois campos de cabeçalho de autenticação para especificar suas credenciais: X-Auth-Username e X-Auth-Password.
A autenticação inicial requer que você execute POST no destino de autenticação (/auth) com o nome do usuário e a senha. O servidor da API RESTful retorna um token hexadecimal. Uma sessão única dura no máximo duas horas ativas ou trinta minutos inativos, o que ocorrer primeiro. Quando sua sessão for encerrada por inatividade, ou se você atingir o tempo máximo alocado, o código de erro 403 indica a perda de autorização. Use o destino de comando /auth para autenticar-se novamente com o nome do usuário e a senha.
https://192.168.10.109:7443/rest/auth, method="POST ",
headers = {0}rd': 'passw0rd'A solicitação de HTTP
que foi enviada para o servidor da API é semelhante a:POST /auth HTTPS/HTTPS_version
Host: https://192.168.10.109:7443
Content-type: application/json; charset = UTF-8
Content-length: message_size
X-Auth-Token: 58cfd6acb1676e1cba78b7cb5a9a081d11d1d1d1cfeb0078083ef225d9c59bf4df
{"attribute": "value","attribute": "value"}
Em
que:- A primeira linha é a linha de solicitação com o método POST, o destino da API, o protocolo (HTTPS) e a versão do protocolo (1.1).
- A segunda linha é o cabeçalho do host, direcionando a solicitação de HTTP para a porta correta (7443) e o endereço IP no sistema.
- A terceira linha é o cabeçalho do tipo de conteúdo que especifica o tipo de conteúdo (application/json; charset=UTF-8).
- A quarta linha é o cabeçalho de comprimento de conteúdo com o tamanho da mensagem.
- A quinta linha é o cabeçalho do token de autenticação com o token de autenticação.
- Um espaço é deixado entre os cabeçalhos e o corpo da solicitação. Quaisquer parâmetros aparecem em JSON na sétima linha.
{
"token": "58cfd6acb1676e1cba78b7cb5a9a081d11d1d1d1cfeb0078083ef225d9c59bf4df"
}Parâmetros de destino do comando
Introdução
O seguinte exemplo Python 3 mostra como concluir a configuração inicial para começar a interagir com o sistema e executar comandos. Para obter exemplos em outros idiomas, consulte Exemplos de uso da API RESTful em Perl e Exemplos de uso em CURL.
import ssl
import json
importar pprint
import urllib.request
import urllib.error
import urllib.parse
no_verify = ssl.create_default_context ()
no_verify.check_hostname = False
no_verify.verify_mode = ssl.CERT_NONE
if getattr (ssl, '_https_verify_certificates', None):
ssl. _https_verify_certificates (False)
class HostString (str):
"""
Comentário: subclasse especial de sequência para armazenar atributos relacionados ao host arbitrário
(como auth tokens) sem perder qualquer comportamento da sequência
"""
def __new__ (cls, * args, ** kwds):
return super (HostString, cls). __new__ (cls, * args, ** kwds)
class RESTUtil(object):
show_default=False
default_headers = {}
port = 80
def __init__(self, show=None, catch=True):
self.hosts = {}
self.curr_host = None
self.catch=catch
self.show_default=show if show != None else self.show_default
@property
def host(self):
return self.curr_host
@host.setter
def host(self, hostname):
"""
Comentário: recupere o objeto HostString de um host conhecido a partir de seu
nome do host ou definição de sequência. Mesmo se a definição do host
for fornecida, ainda será necessário chavear para self.hosts no caso de
classes do cliente estarem armazenando coisas em seus objetos HostString.
"""
try:
if hostname in self.hosts:
self.curr_host = self.hosts[hostname]
else:
self.curr_host = [h for h in self.hosts.values() if h == hostname][0]
return self.curr_host
except IndexError:
raise KeyError("Unrecognized host/name %s" % hostname)
def add_host(self, hostdef, hostname=None):
hostname = hostname if hostname is None else hostdef
self.hosts[hostname] = HostString(hostdef)
if self.curr_host == None:
self.curr_host = self.hosts[hostname]
return hostname
def command(self, protocol, postfix, method='POST', headers=None, show=None, **cmd_kwds):
"""
Comentário: um construtor de solicitação de API RESTful razoavelmente genérico.
Consulte as subclasses para obter exemplos de uso.
"""
if show == None:
show = self.show_default
headers = {} if headers == None else headers
url = '%s://%s:%s/%s' % (
protocol,
self.curr_host,
self.port,
postfix
)
request = urllib.request.Request(
url,
headers =dict(self.default_headers, **headers),
data=bytes(json.dumps(cmd_kwds), encoding="utf-8") if cmd_kwds else None)
request.get_method = lambda: method
if show:
self.request_pprint(request)
try:
cmd_out = urllib.request.urlopen(request, context=no_verify).read().decode('utf-8')
except urllib.error.HTTPError as e:
self.exception_pprint(e)
if not self.catch:
raise Exception("RESTful API command failed.")
return
try:
cmd_out = json.loads(cmd_out)
except ValueError:
pass
if show:
print("\nCommand Output:")
pprint.pprint(cmd_out)
print("")
return cmd_out
@staticmethod
def request_pprint(request):
"""
Comentário: Função de impressão de informações de pedido
(para auto.comando com show = True)
"""
print(request.get_method(), request.get_full_url(), 'HTTP/1.1')
print('Host:', request.host)
for key, value in request.headers.items():
print(key.upper() + ':', str(value))
if request.data != None:
print()
pprint.pprint(request.data)
@staticmethod
def exception_pprint(http_error):
"""
Comentário: função de impressão de informações HTTPError
"""
print (http_error.code, '-- --', http_error.reason)
print (http_error.fp.read ())
print("")
classe SVCREST (RESTUtil):
"""
Comentário: wrapper RESTful para a CLI SVC
"""
def __init__ (self, host, * args, ** kwds):
self.debug = kwds.pop( 'debug', False)
super().__init__(*args, **kwds)
self.add_host (host)
@property
def default_headers (self):
return {'X-Auth-Token': getattr(self.curr_host, 'token', 'badtoken'),
'Content-Type': 'application/json' }
@property
def port (self):
return getattr(self, '_port', None) or ('7665' if self.debug else '7443')
@property
protocolo def (self):
return getattr(self, '_protocol', None) or ('http' if self.debug else 'https')
def command(self, cmd, *args, method="POST", headers=None, show=None, **cmd_kwds):
postfix = '/' .join (
['rest'] + [cmd] + [urllib.parse.quote(str(a)) for a in args]
)
return super( ).comando (
self.protocol,
postfix,
method=method,
headers=headers,
show=show,
** cmd_kwds
)
def authenticate (self, username = 'superuser', password= 'passw0rd', show = None):
cmd_out = self.command (
'auth', show=show, method="POST", headers={'X-Auth-Username': username, 'X-Auth-Password': password}
)
if cmd_out:
self.curr_host.token = cmd_out [ 'token' ]
"""
Comentário: primeiro, configure o ipaddress do cluster.
Supõe-se que superuser/passw0rd (6 linhas acima) seja a credencial.
Após a chamada autenticada, é possível emitir qualquer comando em
s.command('') that is an svcinfo or svctask cmmand)
"""
s = SVCREST( '192.168.10.109')
s.authenticate ()
print (s.command ('lssystem'))